﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using MySql.Data.MySqlClient;
using DateBaseConnectionPool;

namespace TestMySqlConnetPoll
{
    class GybdcTable
    {
        #region 外部函数接口，高压不对称曲线    变量定义
        public class ObjGybdcType
        {
            public short dotnum1;
            public List<ObjValue> qx1 = new List<ObjValue>();            
            public short dotnum2;
            public List<ObjValue> qx2 = new List<ObjValue>();
            public short dotnum3;
            public List<ObjValue> qx3 = new List<ObjValue>();
        }

        public List<DateTime> GYBDCqxTimeList = new List<DateTime>();    //高压不对称时间表
        public objCodeDev GybdcDevNo = new objCodeDev();       //高压不对称值对应的设备号
        public Dictionary<DateTime, ObjGybdcType> GybdcDevValueList = new Dictionary<DateTime, ObjGybdcType>(); //时间做键值

        public bool Ready_GybdcTimeList = false;
        public bool Ready_GybdcValueList = false;


        public struct GybdcThreadStruct
        {
            public string TableName;
            public AnalogCodeType codeType;
            public Int16 dev_no;
            public int u_time;
        }

        public void Read_GybdcCurveTimeList(AnalogCodeType codetype, Int16 dev_no)
        {
            Ready_GybdcTimeList = false;
            GybdcThreadStruct obj = new GybdcThreadStruct();
            obj.TableName = "gybdcqx";
            obj.codeType = codetype;
            obj.dev_no = dev_no;
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadGYBDCqxTimeList), obj);
        }

        public void Read_GybdcCurveValueList(string TableName, AnalogCodeType codetype, Int16 dev_no, DateTime d_time)
        {
            Ready_GybdcValueList = false;
            GybdcThreadStruct obj = new GybdcThreadStruct();
            obj.TableName = "gybdcqx";
            obj.codeType = codetype;
            obj.dev_no = dev_no;
            obj.u_time = (int)MySql.DateTimeToTime_t(d_time);
            ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadReadGYBDCqxValueList), obj);
        }

        #endregion

        #region  高压不对称曲线操作

        /// <summary>
        /// 加入到高压不对称时间列表，只保存单个设备的时间列表
        /// </summary>
        /// <param name="u_time"></param>
        /// <param name="dev_no"></param>
        private void AddToGYBDCqxTimeList(int u_time, AnalogCodeType codetype, short dev_no)
        {
            if (GybdcDevNo.codetype != codetype || GybdcDevNo.dev_no != dev_no)
            {
                GybdcDevNo.dev_no = dev_no;
                GybdcDevNo.codetype = codetype;                
            }
            DateTime t = MySql.Time_tToDateTime(u_time);
            GYBDCqxTimeList.Add(t);
        }

        /// <summary>
        /// 读取高压不对称曲线时间列表，依据设备号
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="dev_no"></param>
        /// <returns></returns>
        private void ThreadReadGYBDCqxTimeList(object o)
        {
            GybdcThreadStruct obj = (GybdcThreadStruct)o;
            string TableName = obj.TableName;
            AnalogCodeType codetype = obj.codeType;
            Int16 dev_no = obj.dev_no;
            if (GybdcDevNo.dev_no == dev_no || GybdcDevNo.codetype == codetype)
            {
                Ready_GybdcTimeList = true;
                return;
            }
            else
            {
                GybdcDevNo.dev_no = -1;
                GybdcDevNo.codetype = AnalogCodeType.None;
                GYBDCqxTimeList.Clear();
                GybdcDevValueList.Clear();
            }
            if (TableName == "") return;
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志

                }
                if (con != null)
                {
                    StringBuilder SelectStatement = new StringBuilder();

                    SelectStatement.Append(string.Format("select(u_time) from{0} where dev_no = {1} and codetype = {2}", TableName, dev_no, codetype));

                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时

                        MySqlDataReader read = selectCommand.ExecuteReader();
                        while (read.Read())
                        {
                            int u_time = read.GetInt32(0);
                            AddToGYBDCqxTimeList(u_time, codetype, dev_no);
                        }
                        read.Close();
                        Ready_GybdcTimeList = true;
                    }
                    catch (MySqlException e)
                    {
                        //写错误日志                        
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        //写错误日志
                    }
                }
            }
        }
        /// <summary>
        /// 检查该条高压不对称曲线是否在内存中
        /// </summary>
        /// <param name="dev_no"></param>
        /// <param name="u_time"></param>
        /// <returns></returns>
        private bool CheckGybdcQxInMemory(AnalogCodeType codetype, Int16 dev_no, int u_time)
        {
            if (GybdcDevNo.dev_no == dev_no || GybdcDevNo.codetype == codetype)
            {
                DateTime d_time = MySql.Time_tToDateTime(u_time);
                if (GybdcDevValueList.ContainsKey(d_time)) return true;
            }
            return false;
        }
        /// <summary>
        /// 把取出的高压不对称曲线加入到缓冲区中
        /// </summary>
        /// <param name="dev_no"></param>
        /// <param name="u_time"></param>
        /// <param name="dot1"></param>
        /// <param name="qx1"></param>
        /// <param name="dot2"></param>
        /// <param name="qx2"></param>
        /// <param name="dot3"></param>
        /// <param name="qx3"></param>
        private void AddToGybdcDevValueList(AnalogCodeType codetype, Int16 dev_no, int u_time, short dot1, byte[] qx1, short dot2, byte[] qx2, short dot3, byte[] qx3)
        {
            ObjGybdcType tmp = new ObjGybdcType();
            tmp.dotnum1 = dot1;
            tmp.dotnum2 = dot2;
            tmp.dotnum3 = dot3;
            
            if (dev_no != GybdcDevNo.dev_no || codetype != GybdcDevNo.codetype)
            {
                GybdcDevNo.dev_no = dev_no;
                GybdcDevNo.codetype = codetype;
            }
            ObjValue tmpValue = new ObjValue();
            string AnalogName = c_Device.GetAnalogTypeName(codetype);
            for(int i =0;i<dot1;i++)
            {
                int low = qx1[i];
                int hig = qx1[i+1];
                int value = hig*256+low;
                tmpValue = c_RealTimeValue.ConvertAnalogValue(AnalogName,(short)value);
                tmp.qx1.Add(tmpValue);
                i++;
            }
            for (int i = 0; i < dot2; i++)
            {
                int low = qx2[i];
                int hig = qx2[i + 1];
                int value = hig * 256 + low;
                tmpValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, (short)value);
                tmp.qx2.Add(tmpValue);
                i++;
            }
            for (int i = 0; i < dot3; i++)
            {
                int low = qx3[i];
                int hig = qx3[i + 1];
                int value = hig * 256 + low;
                tmpValue = c_RealTimeValue.ConvertAnalogValue(AnalogName, (short)value);
                tmp.qx3.Add(tmpValue);
                i++;
            }
            DateTime d_time = MySql.Time_tToDateTime(u_time);
            GybdcDevValueList.Add(d_time, tmp);
        }
        /// <summary>
        /// 从数据库中读取高压不对称数据
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="dev_no"></param>
        /// <param name="u_time"></param>
        /// <returns></returns>
        private void ThreadReadGYBDCqxValueList(object o)
        {
            GybdcThreadStruct obj = (GybdcThreadStruct)o;
            string TableName = obj.TableName;
            AnalogCodeType codetype = obj.codeType;
            Int16 dev_no = obj.dev_no;
            int u_time = obj.u_time;
            if (CheckGybdcQxInMemory(codetype, dev_no, u_time))
            {
                Ready_GybdcValueList = true;
                return;
            }
            if (GybdcDevNo.dev_no != dev_no || GybdcDevNo.codetype != codetype) //换设备清除列表
            {
                GybdcDevNo.dev_no = -1;
                GybdcDevNo.codetype = AnalogCodeType.None;
                GybdcDevValueList.Clear();
            }
            if (TableName == "") return;
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                }
                if (con != null)
                {
                    StringBuilder SelectStatement = new StringBuilder();

                    SelectStatement.Append(string.Format("select(dotNum1,qx1,dotNum2,qx2,dotNum3,qx3) from{0} where dev_no = {1} and u_time = {2} and codetype = {3}", TableName, dev_no, u_time, codetype));

                    try
                    {
                        MySqlCommand selectCommand = new MySqlCommand(SelectStatement.ToString(), con);
                        selectCommand.CommandTimeout = 120;   //120s操作超时

                        MySqlDataReader read = selectCommand.ExecuteReader();
                        while (read.Read())
                        {
                            short dot1 = read.GetInt16(read.GetOrdinal("dotNum1"));
                            byte[] qx1 = new byte[4000];
                            read.GetBytes(read.GetOrdinal("qx1"), 0, qx1, 0, dot1);

                            short dot2 = read.GetInt16(read.GetOrdinal("dotNum2"));
                            byte[] qx2 = new byte[4000];
                            read.GetBytes(read.GetOrdinal("qx2"), 0, qx2, 0, dot2);

                            short dot3 = read.GetInt16(read.GetOrdinal("dotNum3"));
                            byte[] qx3 = new byte[4000];
                            read.GetBytes(read.GetOrdinal("qx3"), 0, qx3, 0, dot3);
                            AddToGybdcDevValueList(codetype, dev_no, u_time, dot1, qx1, dot2, qx2, dot3, qx3);
                        }
                        read.Close();
                        Ready_GybdcValueList = true;
                    }
                    catch (MySqlException e)
                    {
                        //写错误日志                        
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        //写错误日志
                    }
                }
            }
        }

        /// <summary>
        /// 插入高压不对称表
        /// </summary>
        /// <param name="TableName"></param>
        /// <param name="u_time"></param>
        /// <param name="dev_no"></param>
        /// <param name="dotNum1"></param>
        /// <param name="qx1"></param>
        /// <param name="dotNum2"></param>
        /// <param name="qx2"></param>
        /// <param name="dotNum3"></param>
        /// <param name="qx3"></param>
        /// <returns></returns>
        private bool InsertGYBDCqxTable(string TableName, int u_time, AnalogCodeType codetype, Int16 dev_no, Int16 dotNum1, byte[] qx1, Int16 dotNum2, byte[] qx2, Int16 dotNum3, byte[] qx3)
        {
            bool tmpFlag = false;
            if (TableName == "") return tmpFlag;
            if (MySql.c != null && MySql.c.State == PoolState.Run)
            {
                MySqlConnection con = new MySqlConnection();
                string key = TableName + DateTime.Now.Second.ToString() + DateTime.Now.Millisecond.ToString();
                try
                {
                    con = (MySqlConnection)MySql.c.GetConnectionFormPool(key);
                }
                catch (MySqlException ex)
                {
                    //写异常日志
                    tmpFlag = false;
                }

                if (con != null)
                {
                    StringBuilder InsertStatement = new StringBuilder();

                    InsertStatement.Append(string.Format("insert into {0}(u_time,codetype,dev_no,dotNum1,qx1,dotNum2,qx2,dotNum3,qx3)", TableName));

                    InsertStatement.Append("values(?u_time,?codetype,?dev_no,?dotNum1,?qx1,?dotNum2,?qx2,?dotNum3,?qx3)");

                    MySqlCommand InsertCommand = new MySqlCommand(InsertStatement.ToString(), con);

                    InsertCommand.Parameters.Add(new MySqlParameter("?u_time", MySqlDbType.UInt32)).Value = u_time;
                    InsertCommand.Parameters.Add(new MySqlParameter("?codetype", MySqlDbType.Byte)).Value = codetype;
                    InsertCommand.Parameters.Add(new MySqlParameter("?dev_no", MySqlDbType.UInt16)).Value = dev_no;
                    InsertCommand.Parameters.Add(new MySqlParameter("?dotNum1", MySqlDbType.UInt16)).Value = dotNum1;
                    InsertCommand.Parameters.Add(new MySqlParameter("?qx1", MySqlDbType.VarBinary)).Value = qx1.ToArray();
                    InsertCommand.Parameters.Add(new MySqlParameter("?dotNum2", MySqlDbType.UInt16)).Value = dotNum2;
                    InsertCommand.Parameters.Add(new MySqlParameter("?qx2", MySqlDbType.VarBinary)).Value = qx2.ToArray();
                    InsertCommand.Parameters.Add(new MySqlParameter("?dotNum3", MySqlDbType.UInt16)).Value = dotNum3;
                    InsertCommand.Parameters.Add(new MySqlParameter("?qx3", MySqlDbType.VarBinary)).Value = qx3.ToArray();

                    try
                    {
                        int k = InsertCommand.ExecuteNonQuery();
                        if (k == 1) tmpFlag = true;        //写入成功
                        else tmpFlag = false;              //写入失败
                    }
                    catch (MySqlException e)
                    {
                        //写异常日记
                        tmpFlag = false;       //写入失败
                    }
                    try
                    {
                        MySql.c.DisposeConnection(key);
                    }
                    catch (MySqlException e)
                    {
                        //写异常日记
                    }
                }
            }
            return tmpFlag;
        }
        #endregion
    }
}
